package com.kingyea.gradle.jsch;

import java.io.Closeable;
import java.io.File;

import org.apache.log4j.Logger;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.SftpProgressMonitor;
import com.kingyea.gradle.DeploymentException;

import static com.kingyea.gradle.constant.ConstantValues.LINUX_PATH_SEPARATOR;

public class SftpChannel implements Closeable {
	private static final Logger LOGGER = Logger.getLogger(SftpChannel.class);
	private ChannelSftp channel;
	
	public SftpChannel(ChannelSftp channel) {
		this.channel = channel;
	}
	
	@Override
	public void close() {
		channel.quit();
		channel.disconnect();
	}
	
	public void open() throws JSchException {
		channel.connect();
	}
	
	public ChannelSftp getOriginalChannel() {
		return this.channel;
	}
	
	public void uploadDir(String src, String dest, SftpProgressMonitor monitor) {
		File srcDir = new File(src);
		if(srcDir.isFile()) {
			LOGGER.warn(String.format("%s is not a directory, terminated.", src));
			return;
		}
		
		if(!exists(dest)) {
			mkdirs(dest);
		}
		
		File[] files = srcDir.listFiles();
		for(File file : files) {
			String name = file.getName();
			String newDest = dest.endsWith(LINUX_PATH_SEPARATOR) ? dest + name : dest + LINUX_PATH_SEPARATOR + name;
			if(file.isFile()) {
				uploadFile(file.getAbsolutePath(), newDest, monitor);
			} else {
				uploadDir(file.getAbsolutePath(), newDest, monitor);
			}
		}
	}
	
	public void uploadDir(String src, String dest) {
		this.uploadDir(src, dest, null);
	}
	
	public void uploadFile(String src, String dest) {
		this.uploadFile(src, dest, null);
	}
	public void uploadFile(String src, String dest, SftpProgressMonitor monitor) {
		try {
			if(monitor==null) {
				this.channel.put(src, dest, ChannelSftp.OVERWRITE);
			} else {
				this.channel.put(src, dest, monitor, ChannelSftp.OVERWRITE);
			}
		} catch (SftpException e) {
			String message = String.format("upload %s to %s failure.", src, dest);
			throw new DeploymentException(message, e);
		}
	}
	
	public void mkdirs(String path) {
		String[] parts = path.split(LINUX_PATH_SEPARATOR);
		StringBuilder builder = new StringBuilder(LINUX_PATH_SEPARATOR);
		for(String part : parts) {
			builder.append(part);
			String partPath = builder.toString();
			if(!partPath.endsWith(LINUX_PATH_SEPARATOR)) {
				builder.append(LINUX_PATH_SEPARATOR);
				partPath = builder.toString();
			}
			if(!exists(partPath)) {
				mkdir(partPath);
			}
			
		}
	}
	
	public void mkdir(String path) {
		try {
			this.channel.mkdir(path);
		} catch (SftpException e) {
			String message = String.format("directory: %s create failure.", path);
			throw new DeploymentException(message, e);
		}
	}
	
	public boolean exists(String path) {
		try {
			SftpATTRS attrs = this.channel.stat(path);
			return attrs!=null;
		} catch (SftpException e) {
			return false;
		}
	}
	
	public boolean isDir(String path) {
		try {
			SftpATTRS attrs = this.channel.stat(path);
			return attrs.isDir();
		} catch (SftpException e) {
			return false;
		}
	}
	
}
